package speed2010.reformulacao.newQuery;

import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;

import speed2010.reformulacao.dao.User;
import speed2010.reformulacao.query.Log;
import speed2010.reformulacao.query.ReformulationDL;
import speed2010.reformulacao.query.ReformulationProperties;
import speed2010.reformulacao.query.SparqlQuery;
import speed2010.reformulacao.useful.ProfileSession;
import speed2010.reformulacao.useful.Standards;

import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntProperty;
import com.hp.hpl.jena.ontology.OntResource;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;

import edu.stanford.smi.protegex.owl.model.query.QueryResults;

/**
 * Query Formulator
 * 
 * @author Thiago Arruda
 * @author Andrêza Leite
 * @author Bruno Felipe
 * @author Isadora Barros
 */
public class Query {
	
	int tab; // 0 -> DL, 1-> SPARQL, 2-> concept
	String query;
	String querySparql;
	StringBuffer result;
	StringBuffer answerLog;
	
	boolean restricted;
	boolean expanded;
	
	private String path = Standards.fileSource; // @jve:decl-index=0:
	private String template = ""; // @jve:decl-index=0:
	private ArrayList<String> arrayListOntologyElements; // @jve:decl-index=0:
	private Vector<OntProperty> ontologyProperties = new Vector<OntProperty>(); // @jve:decl-index=0:
	private Vector<String> ontElementsVector = new Vector<String>();
	Vector<Integer> integers = new Vector<Integer>(); // @jve:decl-index=0:
	
	String mode = "";
	String reformulationVariables;
	
	private void initialize() {
		this.integers.add(0);

		// Priority of the enriching variables
		Standards.variablesBegin = new DefaultListModel();
		Standards.variablesPriority = new DefaultListModel();
	}
	
	//Load the ontology tree
	private void initializeOntology() {

		OntModel ontology = ModelFactory.createOntologyModel();
		this.ontologyProperties.clear();

		try {
			ontology.read(
					new InputStreamReader(new FileInputStream(this.path)), "");
		} catch (FileNotFoundException e) {
			JOptionPane.showMessageDialog(null, "File not Found");
		}

		this.arrayListOntologyElements = new ArrayList<String>();

		Iterator prop = ontology.listDatatypeProperties();

		while (prop.hasNext()) {
			this.ontologyProperties.add((OntProperty) prop.next());
		}

		for (Iterator it = ontology.listNamedClasses(); it.hasNext();) {
			OntClass c = (OntClass) it.next();

			if (c.isHierarchyRoot()) {
				this.printClassTree(c, "", ontology);
			}
		}
		
	}
	
	//Display the ontology tree
	private void printClassTree(OntClass cls, String indentation,
			OntModel ontology) {

		if (!this.arrayListOntologyElements.contains(cls.getLocalName())) {

			this.ontElementsVector.add(indentation + Standards.conceptUnicode
					+ cls.getLocalName() + "\n");

			Vector<String> properties = this
					.checkProperties(cls.getLocalName());
			for (int i = 0; i < properties.size(); i++) {
				this.ontElementsVector.add(indentation + "   "
						+ Standards.markerUnicode + properties.elementAt(i)
						+ "\n");
			}

			this.arrayListOntologyElements.add(cls.getLocalName());
		}

		Iterator it = cls.listSubClasses();

		while (it.hasNext()) {
			printClassTree((OntClass) it.next(), indentation + "     ",
					ontology);
		}

	}
	
	//Check the concepts' properties
	public Vector<String> checkProperties(String className) {
		Vector<String> properties = new Vector<String>();
		for (int i = 0; i < this.ontologyProperties.size(); i++) {
			ExtendedIterator domains = this.ontologyProperties.elementAt(i)
					.listDomain();
			while (domains.hasNext()) {
				OntResource domain = (OntResource) domains.next();
				String domainName = domain.getLocalName();
				if (className.equals(domainName)) {
					properties.add(this.ontologyProperties.elementAt(i)
							.getLocalName());
					break;
				}
			}
		}
		return properties;
	}
	
	//Rank the results according to user's preferences
	private void rankingPersonalizedResults(Vector<QueryResults> results,
			Vector<String> propertiesUser) {

		Vector<String> perfectResult = new Vector<String>();
		Vector<String> studyResult = new Vector<String>();
		Vector<String> countryResult = new Vector<String>();
		Vector<String> differentResult = new Vector<String>();
		Vector<String> allResults = new Vector<String>();

		User user = ProfileSession.getInstance().getUser();
		// String countryUser = ProfileSession.getInstance().getCountryName();
		String countryUser = user.getNationality();
		String studyareaUser = user.getStudyArea();

		int countProperty = 0;
		String tempAnswer = "";
		String idConcept = "";
		boolean change = false;
		boolean justone = false;

		//Build the answer display - ID, Name, Properties
		if (results.size() > 0) {
			for (int w = 0; w < results.size(); w++) {
				if (results.get(w).hasNext()) {
					while (results.get(w).hasNext()) {

						if (w == 0) {
							if (justone == false) {
								answerLog
										.append("\n\nAnswer for the Source Peer: \n");
								justone = true;
							}
						} else {
							if (change == true && justone == true) {
								answerLog
										.append("\nAnswer for the Target Peer - Exact: \n");
								justone = false;
							} else {
								change = true;
							}
						}
						Map map = results.get(w).next();

						Collection c = map.values();

						Iterator it = c.iterator();

						// Property value
						String property = it.next().toString();

						// Concept ID
						String answer = it.next().toString();
						if (answer.contains("(")) {
							answer = answer.substring(answer.indexOf('(') + 1,
									answer.indexOf(' '));
						}

						if (!idConcept.equals(answer)) {
							if (!idConcept.equals("")) {
								tempAnswer = tempAnswer.substring(0, tempAnswer
										.length() - 2);
								allResults.add(tempAnswer);
								answerLog.append("x = " + tempAnswer + "\n");
								answerLog
										.append("---------------------------------------------------\n");
								tempAnswer = "";
								idConcept = answer;
							} else {
								idConcept = answer;
							}
						}

						Set key = map.keySet();
						
						String stKey = key.toString();
						stKey = stKey.substring(1, stKey.indexOf(" ") - 1);

						if (tempAnswer.equals("")) {
							tempAnswer += answer + " -> ";
						}

						String tempCountProperty = stKey.substring(4, stKey
								.length());
						countProperty = Integer.parseInt(tempCountProperty);

						tempAnswer += propertiesUser
								.elementAt(countProperty - 1)
								+ "=" + property + ", ";

					}// while

				}
			}// for vector results

			if (tempAnswer.length() > 0) {
				tempAnswer = tempAnswer.substring(0, tempAnswer.length() - 2);
			}
			if (!allResults.contains(tempAnswer)) {
				allResults.add(tempAnswer);
				answerLog.append("x = " + tempAnswer + "\n");
				answerLog
						.append("---------------------------------------------------\n");
			}

			if (allResults.size() > 0) {
				String studyareaInstance = "";
				String countryInstance = "";
				for (int i = 0; i < allResults.size(); i++) {
					String result = allResults.get(i);

					if (result.length() > 0) {

						// Properties of the instance
						if (result.contains(",")) {
							studyareaInstance = result.substring(result
									.indexOf("=") + 1, result.indexOf(","));
							countryInstance = result.substring(result
									.lastIndexOf("=") + 1, result.length());
						} else {
							String propertyInstance = result.substring(result
									.indexOf(">") + 2, result.indexOf("="));
							if (propertyInstance.equals("studyarea")) {
								studyareaInstance = result.substring(result
										.indexOf("=") + 1, result.length());
							} else {
								countryInstance = result.substring(result
										.indexOf("=") + 1, result.length());
							}
						}
						String score = "";
						// Comparing with the logged user (studyarea and country)
						if (studyareaInstance.equals(studyareaUser)) {
							score += "s";
						}
						if (countryInstance.equals(countryUser)) {
							score += "c";
						}

						if (score.equals("sc")) {
							perfectResult.add(result);
						} else if (score.equals("s")) {
							studyResult.add(result);
						} else if (score.equals("c")) {
							countryResult.add(result);
						} else {
							differentResult.add(result);
						}
					}

				}// for

				//Country and study area are equal
				if (perfectResult.size() > 0) {
					printPersonalizedResults(perfectResult);
				}
				//Studyarea is equal
				if (studyResult.size() > 0) {
					printPersonalizedResults(studyResult);
				}
				//Country is equal
				if (countryResult.size() > 0) {
					printPersonalizedResults(countryResult);
				}
				//Nothing equal
				if (differentResult.size() > 0) {
					printPersonalizedResults(differentResult);
				}

			}

		} 

	}
	
	//Print ranked results
	private void printPersonalizedResults(Vector<String> results) {
		for (int i = 0; i < results.size(); i++) {
			result.append(results.get(i) + "\n");
			result.append("---------------------------------------------------\n");

		}
	}
	
	// Load the query result on the Screen
	public void loadResultSetSparql(QueryResults results, String peer) {

		if (peer.equals("source")) {
			answerLog.append("\n\nAnswer for the Source Peer: \n");
		} else if (peer.equals("negation")) {
			answerLog.append("\nAnswer for the Target Peer - Negation: \n");
		} else if (peer.equals("approximate")) {
			answerLog.append("\nAnswer for the Target Peer - Approximate: \n");
		} else if (peer.equals("generalize")) {
			answerLog.append("\nAnswer for the Target Peer - Generalize: \n");
		} else if (peer.equals("specialize")) {
			answerLog.append("\nAnswer for the Target Peer - Specialize: \n");
		} else if (peer.equals("compose")) {
			answerLog.append("\nAnswer for the Target Peer - Compose: \n");
		} else if (peer.equals("EXACT_SOURCE")) {
			answerLog.append("\nAnswer for the Target Peer - Exact: \n");
		}

		if (results != null) {
			if (results.hasNext()) {
				while (results.hasNext()) {
					Map map = results.next();

					Collection c = map.values();

					Iterator it = c.iterator();

					while (it.hasNext()) {

						String answer = it.next().toString();
						System.out.println("Answer: " + answer);
						if (answer.contains("(")) {
							answer = answer.substring(answer.indexOf('(') + 1,
									answer.indexOf(' '));
						}

						result.append(answer + "\n");
						result.append("---------------------------------------------------\n");

						answerLog.append("x = " + answer + "\n");
						answerLog.append("---------------------------------------------------\n");
					}

				}// while
			} else {
				System.out.println("Answer: No Answer");
				answerLog.append("No Answer \n");
				answerLog
						.append("---------------------------------------------------\n");
			}
		} else {
			System.out.println("Answer: No Answer");
			answerLog.append("No Answer \n");
			answerLog
					.append("---------------------------------------------------\n");
		}

	}
	
	//Ranks the enriched results according to the enriching variables priority
	private void rankingEnrichedResults(
			HashMap<String, QueryResults> enrichedResults,
			Vector<String> propertiesUser,
			HashMap<String, String> exactEnrichedQueries) {


		// Negation first, if applicable
		loadResultSetSparql(enrichedResults.get("negation"), "negation");

		// Other variables, in the order specified
		boolean app = false;
		boolean gen = false;
		boolean spe = false;
		boolean com = false;

		char element;
		//User doesnt set a priority
		if (Standards.variablesPriority.size() == 0
				&& Standards.variablesBegin.size() > 0) {

			if (exactEnrichedQueries.get("approximate").toString().length() > 0) {
				result.append("\nRESULTS FOR: "
						+ exactEnrichedQueries.get("approximate").toString()
						+ "\n");
			}
			loadResultSetSparql(enrichedResults.get("approximate"),
					"approximate");

			if (exactEnrichedQueries.get("generalize").toString().length() > 0) {
				result.append("\nRESULTS FOR: "
						+ exactEnrichedQueries.get("generalize").toString()
						+ "\n");
			}
			loadResultSetSparql(enrichedResults.get("generalize"), "generalize");

			if (exactEnrichedQueries.get("specialize").toString().length() > 0) {
				result.append("\nRESULTS FOR: "
						+ exactEnrichedQueries.get("specialize").toString()
						+ "\n");
			}
			loadResultSetSparql(enrichedResults.get("specialize"), "specialize");

			if (exactEnrichedQueries.get("compose").toString().length() > 0) {
				result
						.append("\nRESULTS FOR: "
								+ exactEnrichedQueries.get("compose")
										.toString() + "\n");
			}
			loadResultSetSparql(enrichedResults.get("compose"), "compose");
		} else {//User sets a priority and now prints the priority answers
			if (Standards.variablesPriority.size() > 0) {
				for (int i = 0; i < Standards.variablesPriority.size(); i++) {
					element = Standards.variablesPriority.getElementAt(i)
							.toString().charAt(0);
					switch (element) {
					case ('A')://approximate
						if (exactEnrichedQueries.get("approximate").toString()
								.length() > 0) {
							result.append("\nRESULTS FOR: "
									+ exactEnrichedQueries.get("approximate")
											.toString() + "\n");
						}
						loadResultSetSparql(enrichedResults.get("approximate"),
								"approximate");
						app = true;
						break;
					case ('G')://generalize
						if (exactEnrichedQueries.get("generalize").toString()
								.length() > 0) {
							result.append("\nRESULTS FOR: "
									+ exactEnrichedQueries.get("generalize")
											.toString() + "\n");
						}
						loadResultSetSparql(enrichedResults.get("generalize"),
								"generalize");
						gen = true;
						break;
					case ('S')://specialize
						if (exactEnrichedQueries.get("specialize").toString()
								.length() > 0) {
							result.append("\nRESULTS FOR: "
									+ exactEnrichedQueries.get("specialize")
											.toString() + "\n");
						}
						loadResultSetSparql(enrichedResults.get("specialize"),
								"specialize");
						spe = true;
						break;
					case ('C')://compose
						if (exactEnrichedQueries.get("compose").toString()
								.length() > 0) {
							result.append("\nRESULTS FOR: "
									+ exactEnrichedQueries.get("compose")
											.toString() + "\n");
						}
						loadResultSetSparql(enrichedResults.get("compose"),
								"compose");
						com = true;
						break;
					}
				}// for
				if (app == false) {//didnt set a priority for the approximate variable
					if (exactEnrichedQueries != null) {
						if (exactEnrichedQueries.get("approximate").toString()
								.length() > 0) {
							result.append("\nRESULTS FOR: "
									+ exactEnrichedQueries.get("approximate")
											.toString() + "\n");
						}
					}
					loadResultSetSparql(enrichedResults.get("approximate"),
							"approximate");
				}

				if (gen == false) {//didnt set a priority for the generalize variable
					if (exactEnrichedQueries != null) {
						if (exactEnrichedQueries.get("generalize").toString()
								.length() > 0) {
							result.append("\nRESULTS FOR: "
									+ exactEnrichedQueries.get("generalize")
											.toString() + "\n");
						}
					}
					loadResultSetSparql(enrichedResults.get("generalize"),
							"generalize");
				}

				if (spe == false) {//didnt set a priority for the specialize variable
					if (exactEnrichedQueries != null) {
						if (exactEnrichedQueries.get("specialize").toString()
								.length() > 0) {
							result.append("\nRESULTS FOR: "
									+ exactEnrichedQueries.get("specialize")
											.toString() + "\n");
						}
					}
					loadResultSetSparql(enrichedResults.get("specialize"),
							"specialize");
				}

				if (com == false) {//didnt set a priority for the compose variable
					if (exactEnrichedQueries != null) {
						if (exactEnrichedQueries.get("compose").toString()
								.length() > 0) {
							result.append("\nRESULTS FOR: "
									+ exactEnrichedQueries.get("compose")
											.toString() + "\n");
						}
					}
					loadResultSetSparql(enrichedResults.get("compose"),
							"compose");
				}
			}// if
		}

	}
	
	// Load the query result on the Screen (for the Properties Template)
	public void loadResultSetSparqlProperties(QueryResults results,
			String peer, String concept, Vector<String> properties) {

		int countProperty = 0;
		String tempAnswer = "";
		String idConcept = "";

		if (peer.equals("source")) {
			answerLog.append("\nAnswer for the Source Peer: \n\n");
		} else if (peer.equals("target") || peer.equals("EXACT_SOURCE")) {
			answerLog.append("\nAnswer for the Target Peer: \n\n");
		}

		if (results != null) {
			if (results.hasNext()) {
				while (results.hasNext()) {
					Map map = results.next();

					Collection c = map.values();

					Iterator it = c.iterator();

					// Property value
					String property = it.next().toString();

					// Concept ID
					String answer = it.next().toString();
					if (answer.contains("(")) {
						answer = answer.substring(answer.indexOf('(') + 1,
								answer.indexOf(' '));
					}

					if (!idConcept.equals(answer)) {
						if (!idConcept.equals("")) {
							tempAnswer = tempAnswer.substring(0, tempAnswer
									.length() - 2);
							result.append(tempAnswer + "\n");
							result
									.append("---------------------------------------------------\n");
							answerLog.append(tempAnswer + "\n");
							answerLog
									.append("---------------------------------------------------\n");
							tempAnswer = "";
							idConcept = answer;
						} else {
							idConcept = answer;
						}
					}

					Set key = map.keySet();
					System.out.println("KEY: " + key.toString());
					String stKey = key.toString();
					stKey = stKey.substring(1, stKey.indexOf(" ") - 1);

					if (tempAnswer.equals("")) {
						tempAnswer += answer + " -> ";
					}

					System.out.println("Answer: " + answer);

					String tempCountProperty = stKey.substring(4, stKey
							.length());
					countProperty = Integer.parseInt(tempCountProperty);

					tempAnswer += properties.elementAt(countProperty - 1) + "="
							+ property + ", ";

				}// while

				if (!tempAnswer.equals("")) {
					tempAnswer = tempAnswer.substring(0,
							tempAnswer.length() - 2);
					result.append(tempAnswer + "\n");
					result
							.append("---------------------------------------------------\n");
					answerLog.append(tempAnswer + "\n");
					answerLog
							.append("---------------------------------------------------\n");
				}

			} else {
				System.out.println("Answer: No Answer");
				answerLog.append("No Answer \n");
				answerLog
						.append("---------------------------------------------------\n");
			}
		} else {
			System.out.println("Answer: No Answer");
			answerLog.append("No Answer \n");
			answerLog
					.append("---------------------------------------------------\n");
		}
	}
	
	/**
	 * Initializes a newly created Query.
	 * 
	 * @param query - String which contains the query in DL or SPARQL
	 * @param type - choose 0 for DL queries or 1 for SPARQL
	 * @param restricted - set true for a restricted query or false for a enriched one
	 * @param template - for SPARQL queries choose between one of these values -> "One" (for one concept only), "Union", "Intersection", "Negation" or "Properties"
	 */
	public Query(String query, int type, boolean restricted, String template) {
		
		this.initialize();
		this.initializeOntology();
		
		if(type == 0) { //DL
			this.tab  = 0;
			this.query = query;
		} else if (type == 1){ //SPARQL
			this.tab = 1;
			this.querySparql = query;
			this.template = template;
		}
		
		if(restricted) { //restricted
			this.restricted = true;
			this.expanded = false;
		} else { //expanded
			this.expanded = true;
			this.restricted = false;
		}
		
		result = new StringBuffer();
		answerLog = new StringBuffer();
		String mode = "";
		
		// Reformulation mode
		
		if (restricted) {
			mode = "Restricted";
			Standards.restricted = true;
			Standards.complete = false;
		} else if (expanded) {
			mode = "Expanded";
			Standards.restricted = false;
			Standards.complete = true;
		}
		
		reformulationVariables = "No";
		
		// Reformulation Variables
		if (Standards.approximate == true
				|| Standards.generalize == true
				|| Standards.compose == true
				|| Standards.specialize == true) {
			reformulationVariables = "Yes";
		}
		
	}
	
	/**
	 * Executes the query.
	 */
	public void start() {
		
		// Tabs
		
		if (tab == 0) {// DL
			
			if (!query.equals("")) {
				
				ReformulationDL reformulation = new ReformulationDL();
				try {
					//Reformulation method
					HashMap<String, String> exactEnrichedQueries = reformulation
					.reformulate(query,
							Standards.fileCorrespondences,
							mode, Standards.approximate,
							Standards.generalize,
							Standards.compose,
							Standards.specialize, path, "");
					
					// Reformulation LOG
					Log log = new Log();
					log.loadOriginalQueryDL(query,
							mode, reformulationVariables,
							Standards.approximate,
							Standards.generalize,
							Standards.compose,
							Standards.specialize);
					log.loadExactEnrichedQueriesDL(
							exactEnrichedQueries, "dl");
					
					// CODI Log - Context
					BufferedWriter buffer = new BufferedWriter(
							new FileWriter(Standards.codiPath, true));
					
					buffer.newLine();
					buffer.write("<Query>");
					buffer.newLine();
					if (Standards.approximate == true) {
						buffer
						.write("	<Approximate> true </Approximate>");
					} else {
						buffer
						.write("	<Approximate> false </Approximate>");
					}
					buffer.newLine();
					if (Standards.generalize == true) {
						buffer
						.write("	<Generalize> true </Generalize>");
					} else {
						buffer
						.write("	<Generalize> false </Generalize>");
					}
					buffer.newLine();
					if (Standards.compose == true) {
						buffer.write("	<Compose> true </Compose>");
					} else {
						buffer.write("	<Compose> false </Compose>");
					}
					buffer.newLine();
					if (Standards.specialize == true) {
						buffer
						.write("	<Specialize> true </Specialize>");
					} else {
						buffer
						.write("	<Specialize> false </Specialize>");
					}
					buffer.newLine();
					buffer.write("	<ExecutionMode> " + mode
							+ " </ExecutionMode>");
					buffer.newLine();
					buffer.write("</Query>");
					buffer.flush();
					buffer.close();
					
					// Translation DL/SPARQL
					SparqlQuery sparql = new SparqlQuery();
					QueryResults results = null;
					QueryResults exactResults = null;
					QueryResults sourceResults = null;
					HashMap<String, QueryResults> enrichedResults = null;
					String[] exactConcepts = null;
					Vector<String> propertiesUser = new Vector<String>();
					
					// Split the concepts (disjunction)
					if (query.contains(
							Standards.orUnicode)
							&& !query.contains(
									Standards.andUnicode)
									&& !query.contains(
											Standards.notUnicode)) {
						
						exactConcepts = query.split(
								"\\" + Standards.orUnicode);
						
						// Source peer
						for (int i = 0; i < exactConcepts.length; i++) {
							
							exactConcepts[i] = exactConcepts[i]
							                                 .trim();
							
							result.append("RESULTS FOR "
									+ exactConcepts[i] + "\n");
							sourceResults = sparql
							.treatOriginalQuery(
									exactConcepts[i], path,
									integers, "");
							
							propertiesUser.add("studyarea");
							propertiesUser.add("country");
							
							// Target peer
							enrichedResults = sparql
							.treatExactEnrichedQueries(
									exactEnrichedQueries,
									Standards.fileDestiny);
							
							// Exact query
							if (enrichedResults.get("EXACT_SOURCE") != null) {
								exactResults = sparql
								.treatOriginalQuery(
										exactConcepts[i],
										Standards.fileDestiny,
										integers, "");
								
								enrichedResults.remove("EXACT_SOURCE");
							}
							
							//Check if there is an user logged to check his preferences
							if (ProfileSession.getInstance()
									.getUser() != null) {
								Vector<QueryResults> sourceExactResults = new Vector<QueryResults>();
								if (sourceResults != null) {
									sourceExactResults
									.add(sourceResults);
								}
								
								if (exactResults != null) {
									sourceExactResults
									.add(exactResults);
								}
								
								// Ranking source and EXACT_SOURCE answers
								// according to
								// the profile
								rankingPersonalizedResults(
										sourceExactResults,
										propertiesUser);
							} else {
								loadResultSetSparql(sourceResults,
								"source");
								loadResultSetSparql(exactResults,
								"EXACT_SOURCE");
							}
							
						} // for concepts
					} else { // profile on disjunction
						//RESULTS
						result.append("RESULTS FOR "
								+ query + "\n");
						results = sparql.treatOriginalQuery(
								query, path,
								integers, "");
						
						//Preferences
						propertiesUser.add("studyarea");
						propertiesUser.add("country");
						
						// Target peer
						enrichedResults = sparql
						.treatExactEnrichedQueries(
								exactEnrichedQueries,
								Standards.fileDestiny);
						
						if (ProfileSession.getInstance().getUser() != null
								&& !query.contains(
										Standards.orUnicode)
										&& !query.contains(
												Standards.andUnicode)
												&& !query.contains(
														Standards.notUnicode)) {
							
							Vector<QueryResults> sourceExactResults = new Vector<QueryResults>();
							if (results != null) {
								sourceExactResults.add(results);
							}
							if (enrichedResults.get("EXACT_SOURCE") != null) {
								sourceExactResults
								.add(enrichedResults
										.get("EXACT_SOURCE"));
							}
							// Ranking source and EXACT_SOURCE answers
							// according to
							// the profile
							rankingPersonalizedResults(
									sourceExactResults,
									propertiesUser);
							
						} else {
							loadResultSetSparql(results, "source");
						}
					}// else split
					
					// Ranking answers according to the priority
					rankingEnrichedResults(enrichedResults,
							propertiesUser, exactEnrichedQueries);
					
					if (result.equals("")) {
						result.append("No Answer");
					}
					
					
				} catch (Exception e1) {
					e1.printStackTrace();
					JOptionPane
					.showMessageDialog(
							null,
							"Problem(s) encountered to reformulate the query",
							"Query Error",
							Standards.ERROR_MSG);
				}
				
			} else { // Empty query
				JOptionPane.showMessageDialog(null, "Type a query",
						"Error", Standards.ERROR_MSG);
			}
			
		} else if (tab == 2) {// Concept
			
		} else if (tab == 1) {// SPARQL
			
			ReformulationDL reformulation = new ReformulationDL();
			
			try {
				
				if (querySparql.equals("")) {
					JOptionPane.showMessageDialog(null,
							"Type a Query", "Query Error",
							Standards.ERROR_MSG);
					
					//Query for properties
				} else if (template.equals("Properties")) {
					
					ReformulationProperties reformulationProp = new ReformulationProperties();
					
					// Getting concept and properties from the query
					// (source peer)
					String concept = reformulationProp
					.getConcept(querySparql);
					
					Vector<String> properties = reformulationProp
					.getProperties(querySparql);
					
					// Getting concepts and properties from the
					// reformulated query (target peer)
					Vector<String> relatedConcepts = reformulationProp
					.getRelatedConcepts(
							Standards.fileCorrespondences,
							path, concept);
					
					Vector<String> equivalentProperties = reformulationProp
					.getEquivalentProperties(
							Standards.fileCorrespondences,
							path, properties);
					// Reformulation
					Vector<String> reformulatedQueries = reformulationProp
					.treatPropertiesQuery(relatedConcepts,
							equivalentProperties);
					
					// Reformulation LOG
					Log log = new Log();
					log.loadOriginalQueryDLProperty(querySparql);
					
					if (reformulatedQueries.size() > 0) {
						for (int i = 0; i < reformulatedQueries
						.size(); i++) {
							log.loadReformulatedQueriesProperties(
									reformulatedQueries
									.elementAt(i));
						}
					}
					
					// Results
					// Source peer
					QueryResults resultsSourcePeer = null;
					resultsSourcePeer = reformulationProp
					.execQuery(path, querySparql);
					loadResultSetSparqlProperties(
							resultsSourcePeer, "source", concept,
							properties);
					
					// Target peer
					QueryResults resultsTargetPeer = null;
					for (int i = 0; i < reformulatedQueries.size(); i++) {
						resultsTargetPeer = reformulationProp
						.execQuery(Standards.fileDestiny,
								reformulatedQueries
								.elementAt(i));
						loadResultSetSparqlProperties(
								resultsTargetPeer, "target",
								relatedConcepts.elementAt(i),
								equivalentProperties);
					}
					
					if (result.equals("")) {
						result.append("No Answer");
					}
					
				} else {
					
					//Reformulation method - other templates
					HashMap<String, String> exactEnrichedQueries = reformulation
					.reformulate(querySparql,
							Standards.fileCorrespondences,
							mode, Standards.approximate,
							Standards.generalize,
							Standards.compose,
							Standards.specialize, path,
							template);
					
					
					// Reformulation LOG
					Log log = new Log();
					log.loadOriginalQueryDL(querySparql,
							mode, reformulationVariables,
							Standards.approximate,
							Standards.generalize,
							Standards.compose,
							Standards.specialize);
					

					SparqlQuery sparql1 = new SparqlQuery();
					HashMap<String, String> exactEnrichedQuerySparql = new HashMap();
					
					// Enriching variables
					exactEnrichedQuerySparql = sparql1
					.dlBackToSparql(exactEnrichedQueries,
							Standards.fileDestiny);
					
					if (exactEnrichedQuerySparql.get("EXACT_SOURCE") == null) {
						exactEnrichedQuerySparql.put("EXACT_SOURCE", "");
					}
					if (exactEnrichedQuerySparql.get("negation") == null) {
						exactEnrichedQuerySparql
						.put("negation", "");
					}
					if (exactEnrichedQuerySparql.get("approximate") == null) {
						exactEnrichedQuerySparql.put("approximate",
						"");
					}
					if (exactEnrichedQuerySparql.get("generalize") == null) {
						exactEnrichedQuerySparql.put("generalize",
						"");
					}
					if (exactEnrichedQuerySparql.get("specialize") == null) {
						exactEnrichedQuerySparql.put("specialize",
						"");
					}
					if (exactEnrichedQuerySparql.get("compose") == null) {
						exactEnrichedQuerySparql.put("compose", "");
					}
					
					log.loadExactEnrichedQueriesDL(
							exactEnrichedQuerySparql, "sparql");
					
					// CODI Log
					BufferedWriter buffer = new BufferedWriter(
							new FileWriter(Standards.codiPath, true));
					
					buffer.newLine();
					buffer.write("<Query>");
					buffer.newLine();
					if (Standards.approximate == true) {
						buffer
						.write("	<Approximate> true </Approximate>");
					} else {
						buffer
						.write("	<Approximate> false </Approximate>");
					}
					buffer.newLine();
					if (Standards.generalize == true) {
						buffer
						.write("	<Generalize> true </Generalize>");
					} else {
						buffer
						.write("	<Generalize> false </Generalize>");
					}
					buffer.newLine();
					if (Standards.compose == true) {
						buffer.write("	<Compose> true </Compose>");
					} else {
						buffer.write("	<Compose> false </Compose>");
					}
					buffer.newLine();
					if (Standards.specialize == true) {
						buffer
						.write("	<Specialize> true </Specialize>");
					} else {
						buffer
						.write("	<Specialize> false </Specialize>");
					}
					buffer.newLine();
					buffer.write("	<ExecutionMode> " + mode
							+ " </ExecutionMode>");
					buffer.newLine();
					buffer.write("</Query>");
					buffer.flush();
					buffer.close();
					
					// Translation
					SparqlQuery sparql = new SparqlQuery();
					QueryResults results = null;
					HashMap<String, QueryResults> enrichedResults = null;
					
					// Source peer
					results = sparql.treatOriginalQuery(
							querySparql, path, integers, template);
					
					Vector<String> propertiesUser = new Vector<String>();
					propertiesUser.add("studyarea");
					propertiesUser.add("country");
					
					// Target peer
					enrichedResults = sparql
					.treatExactEnrichedQueries(
							exactEnrichedQueries,
							Standards.fileDestiny);
					
					if (ProfileSession.getInstance().getUser() != null
							&& template.equals("One")) {
						Vector<QueryResults> sourceExactResults = new Vector<QueryResults>();
						if (results != null) {
							sourceExactResults.add(results);
						}
						if (enrichedResults.get("EXACT_SOURCE") != null) {
							sourceExactResults.add(enrichedResults
									.get("EXACT_SOURCE"));
						}
						// Ranking source and EXACT_SOURCE answers
						// according to
						// the profile
						rankingPersonalizedResults(
								sourceExactResults, propertiesUser);
					} else {
						loadResultSetSparql(results, "source");
					}
					
					// Ranking answers according to the priority
					rankingEnrichedResults(enrichedResults,
							propertiesUser, null);
					
					if (result.equals("")) {
						result.append("No Answer");
					}
					
				}
				
			} catch (Exception e1) {
				e1.printStackTrace();
				JOptionPane
				.showMessageDialog(
						null,
						"Problem(s) encountered to reformulate the query",
						"Query Error", Standards.ERROR_MSG);
			}
		}
		
	}
	
	/**
	 * Prints the result.
	 */
	public void showResults() {
		System.out.println(result);
	}
	
	/**
	 * Generates a String which represents a SPARQL query.
	 * 
	 * @param template - represents the type of query. Choose between one of these values -> "One" (for one concept only), "Union", "Intersection", "Negation" or "Properties"
	 * @return String which represents a SPARQL query.
	 */
	public static String generateTemplate(String template) {
		
		String path = Standards.fileSource;
		String preQuery = "";
		
		if(template.equals("One")) {
			template = "One";

			SparqlQuery sparql = new SparqlQuery();
			String entityElement = "";
			try {
				entityElement = sparql.getHeaderElement("xml:base",
						path);
			} catch (FileNotFoundException e1) {
				JOptionPane.showMessageDialog(null, "File not found");
			}

			preQuery += "SELECT distinct ?x \n";
			preQuery += "FROM <" + entityElement + ">\n";
			preQuery += "WHERE { \n";
			preQuery += "?x rdf:type <" + entityElement;
			preQuery += "#YY";
			preQuery += "> \n";
			preQuery += "} \n";

		} else if (template.equals("Union")) {
			template = "Union";

			SparqlQuery sparql = new SparqlQuery();
			String entityElement = "";
			try {
				entityElement = sparql.getHeaderElement("xml:base",
						path);
			} catch (FileNotFoundException e1) {
				JOptionPane.showMessageDialog(null, "File not found");
			}

			preQuery += "SELECT distinct ?x \n";
			preQuery += "FROM <" + entityElement + ">\n";
			preQuery += "WHERE { {\n";
			preQuery += "?x rdf:type <" + entityElement + "#YY1> \n";
			preQuery += "} UNION { \n";
			preQuery += "?x rdf:type <" + entityElement + "#YY2> \n";
			preQuery += "} } \n";
			
		} else if(template.equals("Intersection")) {
			template = "Intersection";

			SparqlQuery sparql = new SparqlQuery();
			String entityElement = "";
			try {
				entityElement = sparql.getHeaderElement(
						"xml:base", path);
			} catch (FileNotFoundException e1) {
				JOptionPane.showMessageDialog(null,
						"File not found");
			}

			preQuery += "SELECT distinct ?x \n";
			preQuery += "FROM <" + entityElement + ">\n";
			preQuery += "WHERE { {\n";
			preQuery += "?x rdf:type <" + entityElement
					+ "#YY1> \n";
			preQuery += " . \n";
			preQuery += "?x rdf:type <" + entityElement
					+ "#YY2> \n";
			preQuery += "} } \n";
			
		} else if(template.equals("Negation")) {
			template = "Negation";

			SparqlQuery sparql = new SparqlQuery();
			String entityElement = "";
			try {
				entityElement = sparql.getHeaderElement("xml:base",
						path);
			} catch (FileNotFoundException e1) {
				JOptionPane.showMessageDialog(null, "File not found");
			}

			// Properties template
			preQuery += "SELECT distinct ?x \n";
			preQuery += "FROM <" + entityElement + ">\n";
			preQuery += "WHERE { {\n";
			preQuery += "?x rdf:type ?y . \n";
			preQuery += "<" + entityElement
					+ "#YY> rdfs:subClassOf ?y} UNION {\n";
			preQuery += "?x rdf:type ?z . ";
			preQuery += "<" + entityElement + "#YY> \n";
			preQuery += "rdfs:subClassOf ?y . ?z rdfs:subClassOf ?y . \n";
			preQuery += "FILTER (?z != <" + entityElement
					+ "#YY>) }} \n";
			
		} else if(template.equals("Properties")) {
			template = "Properties";

			SparqlQuery sparql = new SparqlQuery();
			String entityElement = "";
			try {
				entityElement = sparql.getHeaderElement("xml:base",
						path);
			} catch (FileNotFoundException e1) {
				JOptionPane.showMessageDialog(null, "File not found");
			}

			preQuery += "SELECT ?x ?prop1 ?prop2 \n";
			preQuery += "FROM <" + entityElement + ">\n";
			preQuery += "WHERE { \n";
			preQuery += "?x rdf:type <" + entityElement + "#YY1> . \n";
			preQuery += "{ \n";
			preQuery += "?x <" + entityElement + "#prop1> ?prop1\n";
			preQuery += "} UNION { \n";
			preQuery += "?x <" + entityElement + "#prop2> ?prop2 \n";
			preQuery += "} \n";
			preQuery += " } \n";
			// preQuery += "Limit XX";
		}
		
		return preQuery;
	}
	
	public static void main(String[] args) {
//		String templateSPARQL = generateTemplate("Properties");// possiveis parametros: One, Union, Intersection, Negation, Properties
//		System.out.println(templateSPARQL);
//		String consulta = "SELECT ?x ?prop1 ?prop2 FROM <http://swrc.ontoware.org/ontology/portal> WHERE { ?x rdf:type <http://swrc.ontoware.org/ontology/portal#Student> . { ?x <http://swrc.ontoware.org/ontology/portal#studyarea> ?prop1 } UNION { ?x <http://swrc.ontoware.org/ontology/portal#country> ?prop2 }  } ";
//		Query query = new Query(consulta, 1, true, "Properties");
//		query.start();
//		query.showResults();
		Query query = new Query("Person", 1, true,"One");
		query.showResults();
	}
}
